package com.jse.api;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;

import com.jse.Times;
import com.jse.Urls;
import com.jse.json.Json;
import com.jse.json.JsonObject;
import com.jse.web.Ctx;

/**
 * 提供了生成支付宝支付请求的工具方法。
 */
public class Pay {

	private static final String alipay_public_key="MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApmwCeSxwXfq/Dm2pWxrq7TcrIeBzNztf+pdicRZOu8bWDXB+0CsXG6BM2gnPfcRWh0/BPdTmVLEVL1FFi9MzUBjSHiUhLxcuD1/ImR3DQXMf6YntmRr2qGs9xnaMoe6urmf3ri94qeKMloNrmublJwULY8/fUp8A6DFBNEgMJeIUMjtQGtVC+NLzMJuAbqQ7cMDSFmvVDadmW8oPUJXTtmEL5TRjDSLN8dheIiTT0+TVxUvke1ViZDjRmgXpwm7x341ECWLOuWedQ+vrzWnhiP9I8vkI5o+DoA4DGzZgpPtkhl+G3jm26hOAsakiICSC6p0zL/sfd7D8KTcknQTFvQIDAQAB";
	        
    /**
     * 生成手机端支付宝支付链接。
     *
     * @param params 支付参数，必须包含：
     *                <ul>
     *                    <li>private_key (String): 私钥</li>
     *                    <li>app_id (String): 应用ID</li>
     *                    <li>return_url (String): 返回URL</li>
     *                    <li>notify_url (String): 通知URL</li>
     *                    <li>orderno (String): 订单号</li>
     *                    <li>price (Number): 金额</li>
     *                    <li>title (String): 商品标题</li>
     *                    <li>quit_url (String): 用户付款中途退出返回商户网站的地址 (手机端必填)</li>
     *                    <li>body (String): 商品描述 (可选，默认为商品标题)</li>
     *                </ul>
     * @return 支付宝支付链接
     */
    public static String m(Map params) {
        JsonObject param = Json.jsonObject(params);
        String privateKey = param.get("private_key").toString();
        String domain = "https://openapi.alipay.com/gateway.do";
        String timestamp = Times.format();
        Map<String, String> dict = new HashMap<>();
        dict.put("app_id", param.getString("app_id"));
        dict.put("method", "alipay.trade.wap.pay");
        dict.put("return_url", param.getString("return_url"));
        dict.put("enc", "utf-8");
        dict.put("charset", "utf-8");
        dict.put("sign_type", "RSA2");
        dict.put("timestamp", timestamp);
        dict.put("version", "1.0");
        dict.put("notify_url", param.getString("notify_url"));
        String biz_content = "{\"out_trade_no\":\"" + param.get("orderno") +
                "\",\"total_amount\":\"" + param.get("price") +
                "\",\"subject\":\"" + param.get("title") +
                "\",\"quit_url\":\"" + param.get("quit_url") +
                "\",\"body\":\"" + Objects.requireNonNullElse(param.get("body"), param.get("title")) +
                "\",\"product_code\":\"QUICK_WAP_WAY\"}";
        dict.put("biz_content", biz_content);
        String content = Ali.sign(dict);
        String sign = Ali.rsaSign("RSA2", content, privateKey, "utf-8");
        dict.put("sign", sign);
        String ps = Urls.query(dict, StandardCharsets.UTF_8);
        return domain + "?" + ps;
    }

    /**
     * 生成适用于支付宝当面付的二维码链接。
     *
     * @param params 支付参数，必须包含：
     *                <ul>
     *                    <li>private_key (String): 私钥</li>
     *                    <li>app_id (String): 应用ID</li>
     *                    <li>notify_url (String): 通知URL</li>
     *                    <li>orderno (String): 订单号</li>
     *                    <li>price (Number): 金额</li>
     *                    <li>title (String): 商品标题</li>
     *                    <li>body (String): 商品描述 (可选，默认为商品标题)</li>
     *                </ul>
     * @return 支付宝支付链接
     */
    public static String qrcode(Map params) {
        JsonObject param = Json.jsonObject(params);
        String privateKey = param.get("private_key").toString();
        String domain = "https://openapi.alipay.com/gateway.do";
        String timestamp = Times.format();
        Map<String, String> dict = new HashMap<>();
        dict.put("app_id", param.getString("app_id"));
        dict.put("method", "alipay.trade.precreate");
        dict.put("notify_url", param.getString("notify_url"));
        dict.put("charset", "utf-8");
        dict.put("sign_type", "RSA2");
        dict.put("timestamp", timestamp);
        dict.put("version", "1.0");
        String biz_content = "{\"out_trade_no\":\"" + param.get("orderno") +
                "\",\"total_amount\":\"" + param.get("price") +
                "\",\"subject\":\"" + param.get("title") +
                "\",\"body\":\"" + Objects.requireNonNullElse(param.get("body"), param.get("title")) + "\"}";
        dict.put("biz_content", biz_content);
        String content = Ali.sign(dict);
        String sign = Ali.rsaSign(content, privateKey, "utf-8", "RSA2");
        dict.put("sign", sign);
        String ps = Urls.query(dict, StandardCharsets.UTF_8);
        return domain + "?" + ps;
    }

    /**
     * 生成PC端支付宝支付链接。
     *
     * @param params 支付参数，必须包含：
     *                <ul>
     *                    <li>private_key (String): 私钥</li>
     *                    <li>app_id (String): 应用ID</li>
     *                    <li>return_url (String): 返回URL</li>
     *                    <li>notify_url (String): 通知URL</li>
     *                    <li>orderno (String): 订单号</li>
     *                    <li>price (Number): 金额</li>
     *                    <li>title (String): 商品标题</li>
     *                    <li>body (String): 商品描述 (可选，默认为商品标题)</li>
     *                </ul>
     * @return 支付宝支付链接
     */
    public static String pc(Map params) {
        JsonObject param = Json.jsonObject(params);
        String privateKey = param.getString("private_key");
        String domain = "https://openapi.alipay.com/gateway.do";
        String timestamp = Times.format();
        Map<String, String> dict = new HashMap<>();
        dict.put("app_id", param.getString("app_id"));
        dict.put("method", "alipay.trade.page.pay");
        dict.put("return_url", param.getString("return_url"));
        dict.put("charset", "utf-8");
        dict.put("sign_type", "RSA2");
        dict.put("timestamp", timestamp);
        dict.put("version", "1.0");
        dict.put("notify_url", param.getString("notify_url"));
        String biz_content = "{\"out_trade_no\":\"" + param.get("orderno") +
                "\",\"total_amount\":\"" + param.get("price") +
                "\",\"subject\":\"" + param.get("title") +
                "\",\"body\":\"" + Objects.requireNonNullElse(param.get("body"), param.get("title")) +
                "\",\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}";
        dict.put("biz_content", biz_content);
        String content = Ali.sign(dict);
        String sign = Ali.rsaSign(content, privateKey, "utf-8", "RSA2");
        dict.put("sign", sign);
        String ps = Urls.query(dict, StandardCharsets.UTF_8);
        return domain + "?" + ps;
    }

    /**
     * 根据提供的参数自动选择合适的支付方式。
     *
     * @param params 支付参数，必须包含：
     *                <ul>
     *                    <li>private_key (String): 私钥</li>
     *                    <li>app_id (String): 应用ID</li>
     *                    <li>return_url (String): 返回URL (非当面付必填)</li>
     *                    <li>notify_url (String): 通知URL</li>
     *                    <li>orderno (String): 订单号</li>
     *                    <li>price (Number): 金额</li>
     *                    <li>title (String): 商品标题</li>
     *                    <li>body (String): 商品描述 (可选，默认为商品标题)</li>
     *                    <li>quit_url (String): 用户付款中途退出返回商户网站的地址 (手机端必填，当存在此参数时优先调用手机支付接口)</li>
     *                    <li>store_id (String): 商户门店ID (当面付必填，当存在此参数时优先调用当面付接口)</li>
     *                </ul>
     * @return 支付宝支付链接
     */
    public static String pay(Map params) {
        if (params.containsKey("store_id")) {
            return qrcode(params);
        } else if (params.containsKey("quit_url")) {
            return m(params);
        } else {
            return pc(params);
        }
    }

    /**
     * 生成支付宝退款请求。
     *
     * @param params 退款参数，必须包含：
     *                <ul>
     *                    <li>private_key (String): 私钥</li>
     *                    <li>app_id (String): 应用ID</li>
     *                    <li>notify_url (String): 通知URL</li>
     *                    <li>out_trade_no (String): 商户订单号</li>
     *                    <li>refund_amount (Number): 退款金额</li>
     *                    <li>refund_reason (String): 退款原因</li>
     *                </ul>
     * @return 支付宝退款请求链接
     */
    public static String refund(Map params) {
        JsonObject param = Json.jsonObject(params);
        String privateKey = param.getString("private_key");
        String domain = "https://openapi.alipay.com/gateway.do";
        String timestamp = Times.format();
        Map<String, String> dict = new HashMap<>();
        dict.put("app_id", param.getString("app_id"));
        dict.put("method", "alipay.trade.refund");
        dict.put("charset", "utf-8");
        dict.put("sign_type", "RSA2");
        dict.put("timestamp", timestamp);
        dict.put("version", "1.0");
        dict.put("notify_url", param.getString("notify_url"));
        
        String biz_content = "{\"out_trade_no\":\"" + param.get("out_trade_no") +
                "\",\"refund_amount\":\"" + param.get("refund_amount") +
                "\",\"refund_reason\":\"" + param.get("refund_reason") + "\"}";
        dict.put("biz_content", biz_content);

        String content = Ali.sign(dict); // 假设 Ali.sign 是一个已定义好的方法
        String sign = Ali.rsaSign(content, privateKey, "utf-8", "RSA2"); // 假设 Ali.rsaSign 是一个已定义好的方法
        dict.put("sign", sign);
        
        String ps = Urls.query(dict, StandardCharsets.UTF_8);
        return domain + "?" + ps;
    }
    
    /**
     * 生成支付宝统一收单交易查询请求。
     *
     * @param params 查询参数，必须包含：
     *                <ul>
     *                    <li>private_key (String): 私钥</li>
     *                    <li>app_id (String): 应用ID</li>
     *                    <li>trade_no (String): 支付宝交易号</li>
     *                    <li>out_trade_no (String): 商户订单号 (可选)</li>
     *                </ul>
     * @return 支付宝交易查询请求链接
     */
    public static String queryTrade(Map params) {
        JsonObject param = Json.jsonObject(params);
        String privateKey = param.getString("private_key");
        String domain = "https://openapi.alipay.com/gateway.do";
        String timestamp = Times.format();
        Map<String, String> dict = new HashMap<>();
        dict.put("app_id", param.getString("app_id"));
        dict.put("method", "alipay.trade.query");
        dict.put("charset", "utf-8");
        dict.put("sign_type", "RSA2");
        dict.put("timestamp", timestamp);
        dict.put("version", "1.0");
        
        String biz_content = "{\"trade_no\":\"" + param.get("trade_no") +
                             "\",\"out_trade_no\":\"" + param.get("out_trade_no") + "\"}";
        dict.put("biz_content", biz_content);

        String content = Ali.sign(dict); // 假设 Ali.sign 是一个已定义好的方法
        String sign = Ali.rsaSign(content, privateKey, "utf-8", "RSA2"); // 假设 Ali.rsaSign 是一个已定义好的方法
        dict.put("sign", sign);
        
        String ps = Urls.query(dict, StandardCharsets.UTF_8);
        return domain + "?" + ps;
    }
    
    /**
     * 生成支付宝查询对账单下载地址请求。
     *
     * @param params 查询参数，必须包含：
     *                <ul>
     *                    <li>private_key (String): 私钥</li>
     *                    <li>app_id (String): 应用ID</li>
     *                    <li>bill_date (String): 对账单日期，格式为yyyy-MM-dd</li>
     *                    <li>bill_type (String): 对账单类型，可选值：trade、fundbill、income</li>
     *                </ul>
     * @return 支付宝查询对账单下载地址请求链接
     */
    public static String queryBillDownloadUrl(Map params) {
        JsonObject param = Json.jsonObject(params);
        String privateKey = param.getString("private_key");
        String domain = "https://openapi.alipay.com/gateway.do";
        String timestamp = Times.format();
        Map<String, String> dict = new HashMap<>();
        dict.put("app_id", param.getString("app_id"));
        dict.put("method", "alipay.data.dataservice.bill.downloadurl.query");
        dict.put("charset", "utf-8");
        dict.put("sign_type", "RSA2");
        dict.put("timestamp", timestamp);
        dict.put("version", "1.0");
        
        String biz_content = "{\"bill_date\":\"" + param.get("bill_date") +
                             "\",\"bill_type\":\"" + param.get("bill_type") + "\"}";
        dict.put("biz_content", biz_content);

        String content = Ali.sign(dict); // 假设 Ali.sign 是一个已定义好的方法
        String sign = Ali.rsaSign(content, privateKey, "utf-8", "RSA2"); // 假设 Ali.rsaSign 是一个已定义好的方法
        dict.put("sign", sign);
        
        String ps = Urls.query(dict, StandardCharsets.UTF_8);
        return domain + "?" + ps;
    }
    /**
     * 生成支付宝统一收单交易关闭请求。
     *
     * @param params 关闭参数，必须包含：
     *                <ul>
     *                    <li>private_key (String): 私钥</li>
     *                    <li>app_id (String): 应用ID</li>
     *                    <li>out_trade_no (String): 商户订单号</li>
     *                </ul>
     * @return 支付宝交易关闭请求链接
     */
    public static String closeTrade(Map params) {
        JsonObject param = Json.jsonObject(params);
        String privateKey = param.getString("private_key");
        String domain = "https://openapi.alipay.com/gateway.do";
        String timestamp = Times.format();
        Map<String, String> dict = new HashMap<>();
        dict.put("app_id", param.getString("app_id"));
        dict.put("method", "alipay.trade.close");
        dict.put("charset", "utf-8");
        dict.put("sign_type", "RSA2");
        dict.put("timestamp", timestamp);
        dict.put("version", "1.0");
        
        String biz_content = "{\"out_trade_no\":\"" + param.get("out_trade_no") + "\"}";
        dict.put("biz_content", biz_content);

        String content = Ali.sign(dict); // 假设 Ali.sign 是一个已定义好的方法
        String sign = Ali.rsaSign(content, privateKey, "utf-8", "RSA2"); // 假设 Ali.rsaSign 是一个已定义好的方法
        dict.put("sign", sign);
        
        String ps = Urls.query(dict, StandardCharsets.UTF_8);
        return domain + "?" + ps;
    }
    /**
     * 生成支付宝统一收单交易退款查询请求。
     *
     * @param params 查询参数，必须包含：
     *                <ul>
     *                    <li>private_key (String): 私钥</li>
     *                    <li>app_id (String): 应用ID</li>
     *                    <li>out_request_no (String): 商户退款请求号</li>
     *                    <li>out_trade_no (String): 商户订单号 (可选)</li>
     *                    <li>trade_no (String): 支付宝交易号 (可选)</li>
     *                </ul>
     * @return 支付宝交易退款查询请求链接
     */
    public static String queryRefund(Map params) {
        JsonObject param = Json.jsonObject(params);
        String privateKey = param.getString("private_key");
        String domain = "https://openapi.alipay.com/gateway.do";
        String timestamp = Times.format();
        Map<String, String> dict = new HashMap<>();
        dict.put("app_id", param.getString("app_id"));
        dict.put("method", "alipay.trade.fastpay.refund.query");
        dict.put("charset", "utf-8");
        dict.put("sign_type", "RSA2");
        dict.put("timestamp", timestamp);
        dict.put("version", "1.0");
        
        String biz_content = "{\"out_request_no\":\"" + param.get("out_request_no") +
                             "\",\"out_trade_no\":\"" + param.get("out_trade_no") +
                             "\",\"trade_no\":\"" + param.get("trade_no") + "\"}";
        dict.put("biz_content", biz_content);

        String content = Ali.sign(dict); // 假设 Ali.sign 是一个已定义好的方法
        String sign = Ali.rsaSign(content, privateKey, "utf-8", "RSA2"); // 假设 Ali.rsaSign 是一个已定义好的方法
        dict.put("sign", sign);
        
        String ps = Urls.query(dict, StandardCharsets.UTF_8);
        return domain + "?" + ps;
    }
    /**
     * 处理支付宝退款冲退完成通知。
     *
     * @param request 请求对象
     * @return 处理结果，通常返回 "success" 表示成功接收通知
     * @throws Exception 处理过程中可能出现的异常
     */
    public static String handleDepositBackCompleted(Ctx tbl,Function<Ctx,String> fun) throws Exception {
        // 从请求中获取通知参数
        Map<String, String> params = new HashMap<>();
        for (Map.Entry<String,Object> entry : tbl.entrySet()) {
            params.put(entry.getKey(), entry.getValue().toString());
        }
        // 验证签名
        boolean isValid = Ali.rsaCheckV1(params, alipay_public_key, "utf-8", "RSA2");
        if (!isValid) {
            throw new Exception("Invalid signature.");
        }
        // 处理通知中的数据
//        String tradeNo = params.get("trade_no");
//        String outTradeNo = params.get("out_trade_no");
//        String refundAmount = params.get("refund_amount");
//        String outRequestNo = params.get("out_request_no");
        // 在这里添加您的业务逻辑，例如更新数据库状态等
        // ...
        return fun.apply(tbl);// 返回 "success" 表示成功接收通知
    }
    /**
     * 主方法用于测试生成支付宝支付链接。
     *
     * @param args 命令行参数
     * @throws IOException 如果发生输入输出异常
     */
    public static void main(String[] args) throws IOException {
        String private_key = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC8e9BZ7eHz2ooPaPhIwBBqfnXBsAB3d6EjJ1Gm2fHUHb57wnhdezKkr3nCqfcDRcAQSnVSI/ub0TUUXk4N6GN/rGa4Q+hRhzG3H4ZgIpxhs/FafXZprgd2Y2fRV/SenReRWA5NGKG1qh4fulhKfPP7uOxOLAuafGIfTwfTHQ9gxUTQakZhIFZFYtEn3qseUNXFl7gJamzM355JEwIZfCsF4DRU8Sbk1WLquAVA3ay+IWvh5INAPTopIpxjnXJaQP7jq4nDGiqfWWn1CJYkJRuYedX5aRyPeiU8NHdKhFebNRLoadFyPJ+/dhhBZGroZ28YgB/mibv+JIm3petUXyItAgMBAAECggEAJT0BCQNqpNcEd87xXs4zcBbUBRRUw0WrXFqkUya0FIhb3e+qAC4a71aL493Yo5jgPVe4niXly/8lUYTgPvcu0UaqdLVV7OWc+OUNk2jDJLp8cLhg8LglWUqCdGXAOqYmxdxz1t+K821Mzk/uqajOO2lppnglQrxYVn8yuI8BPsji5cdS3KQL8/Q4O8W63b3X1QnttFwrr7Zp3PhhRkrHOBXf6Wwnsz6vuX6xsEoYZs3nBUwOTURhBT4y3NxX/aYdhzMnoxgPulcQ4B/E8EQHz65KsKZ8m9FWvu8Y6KNPHX/IyDPNo3TgFX6z/tLGUxmgBtardyqHuvt+bpi4J801AQKBgQD/wAKa0HwtBPMEVUVIKiGVNl7CAydTzyd/P70mcH4WZqzxtUGulZA2M8IWhH53frt72xTKNP3kBjZTs9VJXR5ceD4ch5PPbZoZouGM4C20VL3fdItMcd7FGooUmIDoecbZwZMsk8ufJUwyiNFTvlmQOzYHkLiV5hdI5TBzY6Ju/QKBgQC8qvksyqHvXG36N8o1kbWCJL0PDKGGXmY8jC164rlTR7XAYjwP2Xbwmydgj2BhcE5+AEP8jo43+QXn006WuF5H/7MLhHKbrkB521prufFkL5rbutvPmHeoQI00wHtVLK62Q+4s1ObFFT6q2eTXnxoRJ1bcgp56DYx5U7OTSy8e8QKBgQCK8bE4lK3x829n2j/CngkSvLAsbXQvRyspKeLEgHcwCmZJBvWBOQZZPDNk8mSW3QZUmsintrR87pcTUG8+5VU6XaU48LtwBRakeOZbF+wcvbFONk37oR2rLej4mYXnR0muQkmH/V+xvZyxE73N5mtYPaLz5z8xSQk7dDCnb+jurQKBgHobbgm/W+8/My6uzQC+vWrtvC7xTdlZX3Hwh77w3mE4GDnbWmQnqwMuZ93m7coilaqXIWlkGke/tELGUCbcTKjspUTfBA4eSTyU64CtZ74f0WpFFd7WHxuWK83oheoqcSkl7hC1+mWzyktpmuKy5nwTqfQt1cPI4RHlSmQaVPUBAoGBALgkhbTEVT+pbh+7EmODrdr2jKVtEkg0szn7Jy/65wonL3Gz3EGujvhDagn5YX1gQUAEfSmy1SjXzAk1EGbLKmUr8P1ztrVz507c3EtEbiWb3EC72QO/24fBVJcOZAakgYkwyH/ZOgXquaZa2nEnDsbxS1FphY8dnbVo5aR0Yfn0";
        Map<String, String> dict = new HashMap<>();
        dict.put("private_key", private_key);
        dict.put("app_id", "2017082208324227");
        dict.put("return_url", "http://www.iepsy.com/pay/alipay/return_url");
        dict.put("notify_url", "http://www.iepsy.com/pay/alipay/notify_url");
        dict.put("orderno", "2017082208324227");
        dict.put("price", "0.01");
        dict.put("title", "2019test");
        System.err.println(pay(dict));
    }
}